package com.ruoyi.system.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.enums.VideoParseResponse;
import com.ruoyi.common.utils.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 小红书视频解析服务
 * @Author: JH-Ahua
 * @CreateTime: 2025/1/15
 */
@Service
public class XiaohongshuService {
    
    private static final Logger logger = LoggerFactory.getLogger(XiaohongshuService.class);
    
    /**
     * 解析小红书视频/图集
     * @param url 小红书分享链接
     * @return 解析结果
     */
    public VideoParseResponse parseXiaohongshuVideo(String url) {
        try {
            // 验证URL
            if (url == null || url.trim().isEmpty()) {
                return new VideoParseResponse(201, "URL为空", null);
            }
            
            // 处理短链接重定向
            String finalUrl = processShortUrl(url);
            if (finalUrl == null) {
                return new VideoParseResponse(400, "无法处理短链接", null);
            }
            
            // 提取笔记ID
            String noteId = extractNoteId(finalUrl);
            if (noteId == null || noteId.isEmpty()) {
                return new VideoParseResponse(400, "无法解析笔记ID", null);
            }
            
            // 构造请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1 Edg/122.0.0.0");
            
            // 请求页面内容
            String response = HttpUtils.get(finalUrl, headers);
            if (response == null || response.isEmpty()) {
                return new VideoParseResponse(201, "解析数据失败", null);
            }
            
            // 解析页面数据
            JsonNode pageData = parsePageData(response);
            if (pageData == null) {
                return new VideoParseResponse(201, "数据查找失败", null);
            }
            
            // 构造返回数据
            VideoParseResponse.VideoData data = buildResponseData(pageData, noteId);
            if (data == null) {
                return new VideoParseResponse(404, "当前分享链接已失效！", null);
            }
            
            return new VideoParseResponse(200, "解析成功", data);
            
        } catch (Exception e) {
            logger.error("解析小红书视频失败", e);
            return new VideoParseResponse(500, "解析失败: " + e.getMessage(), null);
        }
    }
    
    /**
     * 处理短链接重定向
     * @param url 原始URL
     * @return 最终URL
     */
    private String processShortUrl(String url) {
        try {
            URL urlObj = new URL(url);
            String host = urlObj.getHost();
            
            // 如果是xhs.com短链接，转换为xhslink.com格式
            if ("xhs.com".equals(host)) {
                String path = urlObj.getPath();
                String[] parts = path.split("/");
                if (parts.length >= 5) {
                    return "http://xhslink.com/a/" + parts[4];
                }
            }
            
            // 获取重定向后的最终URL
            Map<String, String> headers = new HashMap<>();
            headers.put("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1 Edg/122.0.0.0");
            
            return HttpUtils.getFinalUrl(url, headers);
        } catch (Exception e) {
            logger.error("处理短链接失败", e);
            return url;
        }
    }
    
    /**
     * 从URL中提取笔记ID
     * @param url 小红书链接
     * @return 笔记ID
     */
    private String extractNoteId(String url) {
        try {
            // 定义多个正则表达式模式以匹配不同格式的URL
            String[] patterns = {
                "/discovery/item/([a-zA-Z0-9]+)",     // 发现页面链接
                "/explore/([a-zA-Z0-9]+)",             // 探索页面链接
                "/item/([a-zA-Z0-9]+)",                // 项目详情链接
                "/note/([a-zA-Z0-9]+)",                // 笔记链接
            };

            // 依次尝试每个模式
            for (String patternStr : patterns) {
                Pattern pattern = Pattern.compile(patternStr);
                Matcher matcher = pattern.matcher(url);
                if (matcher.find()) {
                    return matcher.group(1);
                }
            }

            return null;
        } catch (Exception e) {
            logger.error("提取笔记ID失败", e);
            return null;
        }
    }
    
    /**
     * 解析页面数据
     * @param response HTML响应内容
     * @return 页面数据JSON对象
     */
    private JsonNode parsePageData(String response) {
        try {
            // 匹配 window.__INITIAL_STATE__ 数据
            Pattern pattern = Pattern.compile("<script>\\s*window\\.__INITIAL_STATE__\\s*=\\s*({[\\s\\S]*?})</script>", Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher(response);
            
            if (matcher.find()) {
                String jsonData = matcher.group(1);
                // 将 undefined 替换为 null
                jsonData = jsonData.replace("undefined", "null");
                ObjectMapper mapper = new ObjectMapper();
                return mapper.readTree(jsonData);
            }
            
            return null;
        } catch (Exception e) {
            logger.error("解析页面数据失败", e);
            return null;
        }
    }
    
    /**
     * 构造响应数据
     * @param pageData 页面数据
     * @param noteId 笔记ID
     * @return 响应数据
     */
    private VideoParseResponse.VideoData buildResponseData(JsonNode pageData, String noteId) {
        try {
            VideoParseResponse.VideoData data = new VideoParseResponse.VideoData();
            
            // 安全获取数据的方法
            String videoUrl = safeGet(pageData, "note.noteDetailMap." + noteId + ".note.video.media.stream.h264[0].backupUrls[0]");
            if (videoUrl == null) {
                videoUrl = safeGet(pageData, "noteData.data.noteData.video.media.stream.h265[0].masterUrl");
            }
            
            // 获取图片数据（作为备用数据源）
            JsonNode imageData = safeGetNode(pageData, "note.noteDetailMap." + noteId + ".note");
            
            // 获取作者信息
            String author = safeGet(pageData, "noteData.data.noteData.user.nickName");
            if (author == null && imageData != null) {
                author = safeGet(imageData, "user.nickname");
            }
            data.setAuthor(author);
            
            String authorId = safeGet(pageData, "noteData.data.noteData.user.userId");
            if (authorId == null && imageData != null) {
                authorId = safeGet(imageData, "user.userId");
            }
            data.setUid(authorId);
            
            // 获取标题和描述
            String title = safeGet(pageData, "noteData.data.noteData.title");
            if (title == null && imageData != null) {
                title = safeGet(imageData, "title");
            }
            data.setTitle(title);
            
            String desc = safeGet(pageData, "noteData.data.noteData.desc");
            if (desc == null && imageData != null) {
                desc = safeGet(imageData, "desc");
            }
            if (desc == null) {
                desc = safeGet(pageData, "note.noteDetailMap." + noteId + ".note.desc");
            }
            data.setDescription(desc);
            
            // 获取头像和封面
            String avatar = safeGet(pageData, "noteData.data.noteData.user.avatar");
            if (avatar == null && imageData != null) {
                avatar = safeGet(imageData, "user.avatar");
            }
            data.setAvatar(avatar);
            
            String cover = safeGet(pageData, "noteData.data.noteData.imageList[0].url");
            if (cover == null) {
                cover = safeGet(pageData, "note.noteDetailMap." + noteId + ".note.imageList[0].urlDefault");
            }
            data.setCover(cover);
            
            // 设置视频或图片数据
            if (videoUrl != null && !videoUrl.isEmpty()) {
                data.setUrl(videoUrl);
            } else if (imageData != null) {
                // 处理图片数据
                JsonNode imageList = safeGetNode(imageData, "imageList");
                if (imageList != null && imageList.isArray()) {
                    List<String> imageUrls = new ArrayList<>();
                    for (JsonNode imageItem : imageList) {
                        if (imageItem.has("urlDefault")) {
                            imageUrls.add(imageItem.get("urlDefault").asText());
                        }
                    }
                    data.setImages(imageUrls);
                }
            }
            
            return data;
        } catch (Exception e) {
            logger.error("构造响应数据失败", e);
            return null;
        }
    }
    
    /**
     * 安全获取JSON对象中的值
     * @param json JSON对象
     * @param path 路径，用点分隔
     * @return 值
     */
    private String safeGet(JsonNode json, String path) {
        try {
            String[] keys = path.split("\\.");
            JsonNode current = json;
            
            for (String key : keys) {
                if (current == null || current.isNull()) {
                    return null;
                }
                
                if (key.contains("[") && key.contains("]")) {
                    // 处理数组索引
                    String arrayKey = key.substring(0, key.indexOf("["));
                    int index = Integer.parseInt(key.substring(key.indexOf("[") + 1, key.indexOf("]")));
                    
                    current = current.get(arrayKey);
                    if (current != null && current.isArray() && index < current.size()) {
                        current = current.get(index);
                    } else {
                        return null;
                    }
                } else {
                    current = current.get(key);
                }
            }
            
            return current != null && !current.isNull() ? current.asText() : null;
        } catch (Exception e) {
            return null;
        }
    }
    
    /**
     * 安全获取JSON节点
     * @param json JSON对象
     * @param path 路径，用点分隔
     * @return JSON节点
     */
    private JsonNode safeGetNode(JsonNode json, String path) {
        try {
            String[] keys = path.split("\\.");
            JsonNode current = json;
            
            for (String key : keys) {
                if (current == null || current.isNull()) {
                    return null;
                }
                
                current = current.get(key);
            }
            
            return current;
        } catch (Exception e) {
            return null;
        }
    }
}
